
#ifndef XMLFORMAT_H
#define XMLFORMAT_H

#include <BMap>
#include <BDockLayout>
#include <BTreeWidget>
#include <BTextEdit>

using namespace BWE;

enum DocType
{
	DType_NONE,
	DType_HTML,
	DType_MAX,
};

enum XmlType
{
	XType_None,
	XType_Head,
	XType_Tail,
	XType_Text,
	XType_Name,
	XType_Value,
	XType_Annotation,
	XType_Max
};

struct XmlItem : public BThing
{
	XmlItem*	parent = 0;
	XmlType		type = XType_None;
	BString		text;
	BRange		range;
	BRange		headRange;
	BRange		tailRange;
	BArray<BHolder<XmlItem>>	children;
};

typedef BArray<XmlItem*>		XmlItemArray;
typedef BHolder<XmlItem>		XmlItemHolder;
typedef BArray<XmlItemHolder>	XmlItemHolderArray;

class XmlFormat : public BTextFormat
{
public:
	XmlFormat(const BString& name = BString());
	~XmlFormat();

	int topItemCount() const;
	XmlItem* topItem(int index);

	virtual void styled(const BStyle* style) override;
	virtual void changed(const BString& text) override;

	virtual const BFont* font(int pos) const;
	virtual const BColor* back(int pos) const;
	virtual const BColor* color(int pos) const;

protected:
	void createTreeWidget();
	void freshTreeWidget();
	BTreeItem* createTreeItem(XmlItem* item);

	XmlItem* insertXmlItem(int pos, int count, XmlType type, XmlItem* parent = 0);

	bool checkTagName(BString& head, BString& tail);
	int readTagName(const BString& text, BString& tagName);
	void readDoctype(XmlItem* item, BString& text);

	bool readDocument(const BString& xmltext);
	bool readXmlItem(XmlItem* item, const BString& xmltext, BString::const_iterator& cit);
	void readAttribs(XmlItem* item, const BString& xmltext, const BString::const_iterator& begin, const BString::const_iterator& end);

protected:
	void slotAssetChanged(BObject* object, const BValue& value);
	void slotTextEditFramed(BTextEdit* textEdit, const BValue& value);

private:
	BTextEdit*				_textEdit;
	BHolder<BDockLayout>	_dockLayout;
	BTreeWidget*			_treeWidget;
	const BStyle*			_style;
	BMap<XmlType, BColor>	_colorMap;

	BString					_version;
	BString					_encoding;
	DocType					_doctype;
	XmlItemHolderArray		_topItems;
	BMap<int, XmlItem*>		_itemMap;
};

#endif
